﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using Binalyse.Memory;

namespace Binalyse
{
    public class MemoryListBox : ListBox
    {
        public MemoryListBox()
            : base()
        {
            this.DrawMode = DrawMode.OwnerDrawVariable;
        }
        public byte[] GetSelectedData()
        {
            if (SelectedIndex == -1) return null;
            if (SelectedItem is PESection)
            {
                return ((PESection)SelectedItem).Data;
            }
            else if (SelectedItem is Heap)
            {
                return ((Heap)SelectedItem).Data;
            }
            return null;
        }
        string FormatProtectFlag(uint flag)
        {
            string ret;
            switch (flag & 0xFF)
            {
                case Win32API.PAGE_EXECUTE:
                    ret = "PAGE_EXECUTE";
                    break;
                case Win32API.PAGE_EXECUTE_READ:
                    ret = "PAGE_EXECUTE_READ";
                    break;
                case Win32API.PAGE_EXECUTE_WRITECOPY:
                    ret = "PAGE_EXECUTE_WRITECOPY";
                    break;
                case Win32API.PAGE_EXECUTE_READWRITE:
                    ret = "PAGE_EXECUTE_READWRITE";
                    break;
                case Win32API.PAGE_READONLY:
                    ret = "PAGE_READONLY";
                    break;
                case Win32API.PAGE_READWRITE:
                    ret = "PAGE_READWRITE";
                    break;
                case Win32API.PAGE_WRITECOMBINE:
                    ret = "PAGE_WRITECOMBINE";
                    break;
                case Win32API.PAGE_WRITECOPY:
                    ret = "PAGE_WRITECOPY";
                    break;
                default:
                    ret = flag.ToString("X8");
                    break;
            }
            switch (flag & 0xFF00)
            {
                case Win32API.PAGE_GUARD:
                    ret += ",PAGE_GUARD";
                    break;
                case Win32API.PAGE_NOACCESS:
                    ret += ",PAGE_NOACCESS";
                    break;
                case Win32API.PAGE_NOCACHE:
                    ret += ",PAGE_NOCACHE";
                    break;
                default:
                    break;
            }
            return ret;
        }
        string FormatPESection(PESection section)
        {

            string str = "全局内存 " + section.Name;
            str += "\r\nAddress       : 0x" + section.Address.ToString();
            str += "\r\nLength        : 0x" + section.Length.ToString("X8");
            str += "\r\nProtect       : " + FormatProtectFlag(section.Protect);
            str += "\r\n-----------------------------------------------------------";
            return str;
        }
        string FormatHeap(Heap heap)
        {
            string str = "堆内存";
            str += "\r\nAddress       : 0x" + heap.Base.ToString();
            str += "\r\nLength        : 0x" + heap.Length.ToString("X8");
            str += "\r\nProtect       : " + FormatProtectFlag(heap.Protect);
            str += "\r\nBlock Count   : " + heap.Blocks.Count.ToString();
            str += "\r\n-----------------------------------------------------------";
            return str;
        }
        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            base.OnDrawItem(e);
            e.DrawBackground();
            if (e.Index == -1) return;
            try
            {
                object item = Items[e.Index];
                if (item is PESection)
                {
                    e.Graphics.DrawString(FormatPESection((PESection)item), this.Font, new SolidBrush(this.ForeColor), e.Bounds);
                }
                else if (item is Heap)
                {
                    e.Graphics.DrawString(FormatHeap((Heap)item), this.Font, new SolidBrush(this.ForeColor), e.Bounds);
                }
            }
            catch 
            {
                base.OnDrawItem(e);
            }
            
        }
        protected override void OnMeasureItem(MeasureItemEventArgs e)
        {
            base.OnMeasureItem(e);

            if (e.Index == -1) return;
            try
            {
                object item = Items[e.Index];
                if (item is PESection)
                {
                    SizeF size = e.Graphics.MeasureString(FormatPESection((PESection)item), this.Font);
                    e.ItemHeight = (int)size.Height + 2;
                    e.ItemWidth = (int)size.Width + 2;
                } if (item is Heap)
                {
                    SizeF size = e.Graphics.MeasureString(FormatHeap((Heap)item), this.Font);
                    e.ItemHeight = (int)size.Height + 2;
                    e.ItemWidth = (int)size.Width + 2;
                }
            }
            catch
            {
                base.OnMeasureItem(e);
            }
        }
    }
}
